package trycache

type TryFunc func()

type CatchFunc func(ex interface{})

type FinallyFunc func()

type TryCache interface {
	Catch(f CatchFunc) TryCache
	Finally(f FinallyFunc)
}

type tryCache struct {
	try   TryFunc
	tried bool
}

func (t *tryCache) Catch(cache CatchFunc) (ret TryCache) {
	if t.try == nil || t.tried {
		return t
	}
	defer func() {
		t.tried = true
		err := recover()
		ret = t
		if err != nil && cache != nil {
			cache(err)
		}
	}()
	t.try()
	return
}

func (t *tryCache) Finally(f FinallyFunc) {
	if !t.tried {
		t.Catch(nil)
	}
	if f != nil {
		f()
	}
}

func Try(try TryFunc) TryCache {
	return &tryCache{try: try}
}
